package com.seaboxdata.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.seaboxdata.entity.*;
import com.seaboxdata.service.DataShareInfoService;
import com.seaboxdata.service.IndicatorsService;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;

/**
 * 大屏指标统计计算
 * @author lh
 * @create 2021-09-22 10:18
 **/
@RestController
@EnableAutoConfiguration
@RequestMapping("/indicators")
public class IndicatorsController {
    private static Logger log = LoggerFactory.getLogger(IndicatorsController.class);

    private static Map<String,String> mapReal;

    private static Map<String,Map<String,Object>> mapShare;

    private static Map<String,Map<String,Object>> mapSource;

    private static Map<String,Map<String,Object>> mapDtype;

    private static Map<String,Map<String,Object>> mapService;

    private static Map<String,Map<String,Object>> mapWay;

    private static Map<String,String> mapCircle;

    private static Map<String,String> mapEpi;

    private static Map<String,String> mapAccess;

    private static Map<String,Map<String,Object>> mapGover;

    @Autowired
    private IndicatorsService indicatorsService;

    @Autowired
    private DataShareInfoService dataShareInfoService;

    /**
     * 数据共享
     * @return
     */
    @RequestMapping(value = "/getSharedInfo")
    public Map<String, Object> getSharedInfo(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if(mapShare == null){
            mapShare = new HashMap<>();
            mapShare.put(today,indicatorsService.getSharedInfo());
        }else{
            if(mapShare.get(today) != null){
                if(mapShare.get(yesterday) != null){
                    mapShare.remove(yesterday);
                }
                return mapShare.get(today);
            }else{
                return indicatorsService.getSharedInfo();
            }
        }
        return indicatorsService.getSharedInfo();
    }

    /**
     * 中间球：指标接入总数据量=静态+实时
     * @return
     */
    @RequestMapping(value = "/getStaRealInfo")
    public Long getStaRealInfo(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if(mapReal == null){
            mapReal = new HashMap<>();
            mapReal.put(today,String.valueOf(indicatorsService.getStaRealInfo()));
        }else{
            if(mapReal.get(today) != null){
                if(mapReal.get(yesterday) != null){
                    mapReal.remove(yesterday);
                }
                return Long.valueOf(mapReal.get(today));
            }else{
                return indicatorsService.getStaRealInfo();
            }
        }
        return indicatorsService.getStaRealInfo();
    }

    /**
     * 数据共享：数据存储量=获取共享表总占用存储空间
     * @return
     */
    @RequestMapping(value = "/getDataSharedSize")
    public String getDataSharedSize(){
        String totalStorage = dataShareInfoService.getDataSharedSize();
        BigDecimal bigDecimal = new BigDecimal(totalStorage);
        BigDecimal storage = bigDecimal.divide(BigDecimal.valueOf(1024L * 1024L * 1024L), 2, BigDecimal.ROUND_HALF_UP);
        return storage + "GB";//占用存储数据量
    }

    /**
     * 数据来源
     * @return
     */
    @RequestMapping(value = "/getDataSourceInfo")
    public Map<String, Object> getDataSourceInfo(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if(mapSource == null){
            mapSource = new HashMap<>();
            mapSource.put(today,indicatorsService.getDataSourceInfo());
        }else{
            if(mapSource.get(today) != null){
                if(mapSource.get(yesterday) != null){
                    mapSource.remove(yesterday);
                }
                return mapSource.get(today);
            }else{
                return indicatorsService.getDataSourceInfo();
            }
        }
        return indicatorsService.getDataSourceInfo();
    }

    /**
     * 基础库
     * @return
     */
    @RequestMapping(value = "/getDTypeInfo")
    public Map<String, Object> getDTypeInfo(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if(mapDtype == null){
            mapDtype = new HashMap<>();
            mapDtype.put(today,indicatorsService.getDTypeInfo());
        }else{
            if(mapDtype.get(today) != null){
                if(mapDtype.get(yesterday) != null){
                    mapDtype.remove(yesterday);
                }
                return mapDtype.get(today);
            }else{
                return indicatorsService.getDTypeInfo();
            }
        }
        return indicatorsService.getDTypeInfo();
    }

    /**
     * 服务能力、共享方式对比（文件、接口服务）
     *
     * @return
     */
    @RequestMapping(value = "/getServiceInfo")
    public List<ServiceInfo> getServiceInfo() {
        return indicatorsService.getServiceInfo();
    }

    /**
     * 共享方式对比（纳管接口、部门指标、部门专题）
     * @return
     */
    @RequestMapping(value = "/getShareWayInfo")
    public Map<String, Object> getShareWayInfo(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if(mapWay == null){
            mapWay = new HashMap<>();
            mapWay.put(today,indicatorsService.getShareWayInfo());
        }else{
            if(mapWay.get(today) != null){
                if(mapWay.get(yesterday) != null){
                    mapWay.remove(yesterday);
                }
                return mapWay.get(today);
            } else {
                return indicatorsService.getShareWayInfo();
            }
        }
        return indicatorsService.getShareWayInfo();
    }

    /**
     * 中间球：获取委办局各use使用 总数据量
     *
     * @return
     */
    @RequestMapping(value = "/getUseCirclesInfo")
    public List<CirclesDepartment> getUseCirclesInfo() {
        return indicatorsService.getUseCirclesInfo();
    }


    /**
     * 中间球：获取委办局各 provide接入 总数据量
     *
     * @return
     */
    @RequestMapping(value = "/getProvideCirclesInfo")
    public List<CirclesDepartment> getProvideCirclesInfo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if (mapCircle == null) {
            mapCircle = new HashMap<>();
            List<CirclesDepartment> list = indicatorsService.getProvideCirclesInfo();
            mapCircle.put(today, JSON.toJSONString(list));
        } else {
            if (mapCircle.get(today) != null){
                if(mapCircle.get(yesterday) != null){
                    mapCircle.remove(yesterday);
                }
                return (List<CirclesDepartment>)JSON.parse(mapCircle.get(today));
            }else {
                return indicatorsService.getProvideCirclesInfo();
            }
        }
        return indicatorsService.getProvideCirclesInfo();
    }




    /**
     * 获取疫情数据统计量：人口基数、核酸检测、疫苗接种
     * @return
     */
    @RequestMapping(value = "/getEpidemicDataInfo")
    public List<EpidemicDataInfo> getEpidemicDataInfo(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if(mapEpi == null){
            mapEpi = new HashMap<>();
            List<EpidemicDataInfo> list = indicatorsService.getEpidemicDataInfo();
            mapEpi.put(today, JSON.toJSONString(list));
        }else{
            if(mapEpi.get(today) != null){
                if(mapEpi.get(yesterday) != null){
                    mapEpi.remove(yesterday);
                }
                return (List<EpidemicDataInfo>)JSON.parse(mapEpi.get(today));
            }else{
                return indicatorsService.getEpidemicDataInfo();
            }
        }
        return indicatorsService.getEpidemicDataInfo();
    }


    /**
     *
     * 获取 type=hot_data 热门数据，当天数据；
     * @return
     */
    @RequestMapping(value = "/getDataCountInfo")
    public List<DataCountInfo> getDataCountInfo(String type){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if(mapAccess == null|| mapAccess.get(today + type) == null){
            mapAccess = new HashMap<>();
            List<DataCountInfo> list = indicatorsService.getDataCountInfo(type);
            mapAccess.put(today + type, JSON.toJSONString(list));
        }else{
            if(mapAccess.get(today + type) != null){
                if(mapAccess.get(yesterday + type) != null) {
                    mapAccess.remove(yesterday + type);
                }
                return (List<DataCountInfo>) JSON.parse(mapAccess.get(today + type));
            } else {
                return indicatorsService.getDataCountInfo(type);
            }
        }
        return indicatorsService.getDataCountInfo(type);
    }


    /**
     * 获取 type=access_way 接入方式对比，获取最近前7天数据；
     * 获取 type=hot_data 热门数据，当天数据；
     *
     * @return
     */
    @RequestMapping(value = "/getDataCompCountInfo")
    public List<DataItemType> getDataCountInfo() {
        return indicatorsService.getDataCompCountInfo();
    }

    /**
     * 获取委办局 使用 总数据量,插入到表中
     */
    @Scheduled(cron = "0 39 1 * * ?")    //每天凌晨1点执行
    public void execCirclesUseScheduled() {
        long totalTime = 0;
        long startTime = System.currentTimeMillis();
        String type = "use";
        log.info("========定时每天凌晨1点获取委办局使用总数据量开始执行========");
        List<CirclesDepartment> departDbList = indicatorsService.getShareDbInfo();
        log.info("========删除当天的委办局使用总数据量数据========"+ LocalDate.now());
        indicatorsService.delCirclesDepartmentInfo(type);
        departDbList.stream().forEach(item ->{
            int tableCount = 0;
            if(StringUtils.isNotEmpty(item.getTableName())){
                String tableName = item.getSchemaName()+"."+item.getTableName();
                try {
                    tableCount = indicatorsService.getCountByTable(tableName);
                } catch (Exception e) {
                    item.setTableDataCount(0);
                    item.setNote("getCountByTable "+tableName+" error! "+e.getMessage());
                }
            }
            item.setCountType(type);//使用
            item.setCreateDate(new Date());
            item.setTableDataCount(tableCount);
            boolean isInsert = indicatorsService.insertCirclesDepartmentInfo(item);
            if(isInsert){
                log.info("执行成功，定时获取委办局使用总数据量成功！结果集：{}", JSON.toJSONString(item));
            }else {
                log.info("执行失败，结果集：{}", JSON.toJSONString(item));
            }
        });
        long endTime = System.currentTimeMillis();
        totalTime =  endTime - startTime;
        log.info("耗时：{},执行{}条",totalTime/60000+"min",departDbList.size());
    }
    /**
     * 获取委办局提供（接入）总数据量,插入到表中
     */
    @Scheduled(cron="0 0 1 * * ?")    //每天凌晨1点半执行
    public void execCirclesTableScheduled() {
        long totalTime = 0;
        long startTime = System.currentTimeMillis();
        String type = "provide";
        log.info("========定时每天凌晨1点获取委办局接入总数据量开始执行========");
        List<CirclesDepartment> departDbList = indicatorsService.getDepartmentDbInfo();
        log.info("========删除当天的委办局接入总数据量数据========"+ LocalDate.now());
        indicatorsService.delCirclesDepartmentInfo(type);
        departDbList.stream().forEach(item ->{
            int tableCount = 0;
            if(StringUtils.isNotEmpty(item.getTableName())){
                String tableName = item.getSchemaName()+"."+item.getTableName();
                try {
                    tableCount = indicatorsService.getCountByTable(tableName);
                } catch (Exception e) {
                    item.setTableDataCount(0);
                    item.setNote("getCountByTable "+tableName+" error! "+e.getMessage());
                }
            }
            item.setCountType(type);//接入
            item.setCreateDate(new Date());
            item.setTableDataCount(tableCount);
            boolean isInsert = indicatorsService.insertCirclesDepartmentInfo(item);
            if(isInsert){
                log.info("执行成功，定时获取委办局接入总数据量成功！结果集：{}", JSON.toJSONString(item));
            }else {
                log.info("执行失败，结果集：{}", JSON.toJSONString(item));
            }
        });
        long endTime = System.currentTimeMillis();
        totalTime =  endTime - startTime;
        log.info("耗时：{},执行{}条",totalTime/1000+"s",departDbList.size());
    }
    /**
     * 获取共享表所占存储空间,插入到表中
     */
    @Scheduled(cron="0 0 1 * * ?")    //每天凌晨1点执行
    public void execShareSpaceScheduled() {
        long totalTime = 0;
        long startTime = System.currentTimeMillis();
        log.info("========定时每天凌晨1点获取共享表所占存储空间开始执行========");
        List<DataShareInfo> shareDbInfoList = indicatorsService.getDataShareDbInfo();
        int[] index = {1};
        shareDbInfoList.stream().forEach(item ->{
            String spaceSize = "0";
            if(StringUtils.isNotEmpty(item.getTableName())){
                String tableName = "'"+item.getSchemaName()+"."+item.getTableName()+"'";
                try {
                    spaceSize = indicatorsService.getSpaceSizeByTable(tableName);
                } catch (Exception e) {
                    item.setTableSpaceSize("0");
                    item.setNote("getCountByTable "+tableName+" error! "+e.getMessage());
                }
            }
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            item.setCreateDate(new Date());
            item.setTableSpaceSize(spaceSize);
            log.info("当前执行第{}条，获取共享表所占存储空间结果：{}",index[0]++,JSON.toJSONString(item));
        });
        boolean isInsert = indicatorsService.insertDataShareInfo(shareDbInfoList);
        if(isInsert){
            log.info("执行成功，定时每天凌晨1点获取共享表所占存储空间成功！结果集：{}", JSON.toJSONString(shareDbInfoList));
        }else {
            log.info("执行失败，结果集：{}", JSON.toJSONString(shareDbInfoList));
        }
        long endTime = System.currentTimeMillis();
        totalTime =  endTime - startTime;
        log.info("耗时：{},执行{}条",totalTime/1000+"s",shareDbInfoList.size());
    }

    /**
     * 获取指标实时接入数据,插入到表中
     */
    @Scheduled(cron="0 0 1 * * ?")    //每天凌晨1点执行
    public void execRealDataIncrementScheduled() {
        long totalTime = 0;
        long startTime = System.currentTimeMillis();
        log.info("========定时每天凌晨1点获取指标实时接入数据开始执行========");
        List<DataRealInfo> freRealList = indicatorsService.getFreRealInfo();
        int[] index = {1};
        freRealList.stream().forEach(item ->{
            Integer dataCount = 0;
            if(StringUtils.isNotEmpty(item.getTableName())){
                String tableName = item.getSchemaName()+"."+item.getTableName();
                try {
                    dataCount = indicatorsService.getCountByTable(tableName);
                } catch (Exception e) {
                    item.setTableDataCount(0);
                    item.setNote("getCountByTable "+tableName+" error! "+e.getMessage());
                }
            }
            item.setCreateDate(new Date());
            item.setTableDataCount(dataCount);
            log.info("当前执行第{}条，获取指标实时接入数据结果：{}",index[0]++,JSON.toJSONString(item));
        });
        boolean isInsert = indicatorsService.insertDataRealInfo(freRealList);
        if(isInsert){
            log.info("执行成功，定时每天凌晨1点获取指标实时接入数据成功！结果集：{}", JSON.toJSONString(freRealList));
        }else {
            log.info("执行失败，结果集：{}", JSON.toJSONString(freRealList));
        }
        long endTime = System.currentTimeMillis();
        totalTime =  endTime - startTime;
        log.info("耗时：{},执行{}条",totalTime/1000+"s",freRealList.size());
    }

    /**
     * 获取疫情数据,插入到表中
     */
    @Scheduled(cron="0 0 1 * * ?")    //每天凌晨1点执行
    public void execEpidemicDataScheduled() {
        long totalTime = 0;
        long startTime = System.currentTimeMillis();
        Date date = new Date();
        log.info("========定时每天凌晨1点获取疫情数据开始执行========");
        Integer peopleNumber = indicatorsService.getPeopleNumber();
        Integer hstestNumber = indicatorsService.getHstestNumber(date);
        Integer ymjzNumber = indicatorsService.getYmjzNumber();

        EpidemicDataInfo epidemicDataInfo = new EpidemicDataInfo();
        epidemicDataInfo.setPeopleNumber(peopleNumber);
        epidemicDataInfo.setHstestNumber(hstestNumber);
        epidemicDataInfo.setYmjzNumber(ymjzNumber);
        epidemicDataInfo.setCreateDate(new Date());
        boolean isInsert = indicatorsService.insertEpidemicDataInfo(epidemicDataInfo);
        if(isInsert){
            log.info("执行成功，定时每天凌晨1点获取疫情数据插入成功！结果集：{}", JSON.toJSONString(epidemicDataInfo));
        }else {
            log.info("执行失败，结果集：{}", JSON.toJSONString(epidemicDataInfo));
        }
        long endTime = System.currentTimeMillis();
        totalTime =  endTime - startTime;
        log.info("耗时：{},执行1条",totalTime/1000+"s");
    }

    /**
     * 获取接入方式对比数据,插入到表中
     * 备注：要在execCirclesTableScheduled之后执行
     */
    @Scheduled(cron="0 30 1 * * ?")    //每天凌晨1点执行
//    @Scheduled(cron="0/10 * * * * ?")   //每隔一秒执行
    public void execAccessWayScheduled() {
        long totalTime = 0;
        long startTime = System.currentTimeMillis();
        String type = "access_way";
        log.info("========定时每天凌晨1点获取接入方式对比数据开始执行========");
        List<DataCountInfo> accessWayList = indicatorsService.getAccessWayInfo();
        if(accessWayList.size()>0){
            log.info("========删除当天的接入方式对比数据========"+ LocalDate.now());
            indicatorsService.delDataCountInfo(type);
            boolean isInsert = indicatorsService.insertDataCountInfo(accessWayList);
            if(isInsert){
                log.info("执行成功，定时每天凌晨1点获取接入方式对比数据成功！结果集：{}", JSON.toJSONString(accessWayList));
            }else {
                log.info("执行失败，结果集：{}", JSON.toJSONString(accessWayList));
            }
        }

        long endTime = System.currentTimeMillis();
        totalTime =  endTime - startTime;
        log.info("耗时：{},执行{}条",totalTime/1000+"s",accessWayList.size());
    }

    /**
     * 获取热门数据,插入到表中
     * 备注：要在execCirclesTableScheduled之后执行
     */
    @Scheduled(cron="0 30 1 * * ?")    //每天凌晨1点执行
    public void execHotDataScheduled() {
        long totalTime = 0;
        long startTime = System.currentTimeMillis();
        String type = "hot_data";
        log.info("========定时每天凌晨1点获取热门数据开始执行========");
        List<DataCountInfo> accessWayList = indicatorsService.getHotDataInfo();
        if(accessWayList.size()>0){
            log.info("========删除当天的热门数据========"+ LocalDate.now());
            indicatorsService.delDataCountInfo(type);
            boolean isInsert = indicatorsService.insertDataCountInfo(accessWayList);
            if(isInsert){
                log.info("执行成功，定时每天凌晨1点获取接入方式对比数据成功！结果集：{}", JSON.toJSONString(accessWayList));
            }else {
                log.info("执行失败，结果集：{}", JSON.toJSONString(accessWayList));
            }
        }

        long endTime = System.currentTimeMillis();
        totalTime =  endTime - startTime;
        log.info("耗时：{},执行{}条",totalTime/1000+"s",accessWayList.size());
    }


    /**
     * 数据治理
     * @return
     */
    @RequestMapping(value = "/getGovernanceInfo")
    public Map<String, Object> getGovernanceInfo(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String today = sdf.format(date);
        String yesterday = sdf.format(DateUtils.addDays(date, -1));
        if(mapGover == null){
            mapGover = new HashMap<>();
            mapGover.put(today,indicatorsService.getGovernanceInfo());
        }else{
            if(mapGover.get(today) != null) {
                if (mapGover.get(yesterday) != null) {
                    mapGover.remove(yesterday);
                }
                return mapGover.get(today);
            } else {
                return indicatorsService.getGovernanceInfo();
            }
        }
        return indicatorsService.getGovernanceInfo();
    }


    /**
     * 查询系统来源(0-省市，1-新区，2-社会)数据量
     *
     * @return
     */
    @RequestMapping(value = "/getSysGovDataInfo")
    public List<CirclesDepartment> getSysGovDataInfo() {
        return indicatorsService.getSysGovDataInfo();
    }


    /**
     * 查询资源数量排名-接入数量  （0-其他，1-接口）
     *
     * @return
     */
    @RequestMapping("/getResDataRankInfo")
    public List<CirclesDepartment> getResDataRankInfo() {
        return indicatorsService.getResDataRankInfo();
    }


    /**
     * 查询数据资源情况-基础/主题/专题
     *
     * @return
     */
    @RequestMapping("/getResDbDataInfo")
    public List<CirclesDepartment> getResDbDataInfo() {
        return indicatorsService.getResDbDataInfo();
    }

    /**
     * 越境司机预警数据
     */
    @GetMapping("/getCrossDriverInfo")
    public List<EpidemicDataInfo> getCrossDriverInfo() {
        return indicatorsService.getCrossDriverInfo();
    }


    /**
     * 获取实时总数据量
     */
    @GetMapping("/getActualTimeDataInfo")
    public long getActualTimeDataInfo() {
        long startTime = System.currentTimeMillis();
        long totalCount = 0;
        List<DataShareInfo> shareDbInfoList = dataShareInfoService.getActualTimeDataInfo();
        if (!CollectionUtils.isEmpty(shareDbInfoList)) {
            for (DataShareInfo dataShareInfo : shareDbInfoList) {
                String tabName = dataShareInfo.getSchemaName().concat(".")
                        .concat(dataShareInfo.getTableName().substring(5));
                int spaceSize = dataShareInfoService.getTableSizeByTable(tabName);
                totalCount += spaceSize;
            }
        }
        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        log.info("耗时：{},执行{}条", totalTime / 1000 + "s", totalCount);
        return totalCount;
    }


    /**
     * 获取数据汇聚表空间
     */
    @GetMapping("/getMppDbSpaceDataInfo")
    public String getMppDbSpaceDataInfo() {
        String size = dataShareInfoService.getMppDbSpaceDataInfo();
        return size;
    }


}
